{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a name=\"top\"></a><img src=\"./source/SpinalHDL.png\" alt=\"SpinalHDL based on Scala\" style=\"width:320px;\" />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "  Before running Spinal HDL code, be sure to load SpinalHDL Libraries  \n",
    "**Note** : This may be a little slow when the first time load, please wait a moment to download Lib from remote.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "val path = System.getProperty(\"user.dir\") + \"/source/load-spinal.sc\"\n",
    "interp.load.module(ammonite.ops.Path(java.nio.file.FileSystems.getDefault().getPath(path)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Chapter\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class spRAM(aw: Int, dw: Int, x: Vendor, memName: String = \"\") extends Component with MemWrap{\n",
    "  val io = new Bundle{\n",
    "    val cs, wr = in Bool()\n",
    "    val addr   = in UInt(aw bits)\n",
    "    val wdata  = in Bits(dw bits)\n",
    "    val rdata  = out Bits(dw bits)\n",
    "  }\n",
    "  noIoPrefix() \n",
    "  val ram = new bf_rfsp(mc, memName)\n",
    "  ram.Build(this)\n",
    "}\n",
    "\n",
    "trait Vendor{\n",
    "    def rfspMem(mc: MemConfig): MemBlackBox = {new rfsp(mc)}    \n",
    "    def rf2pMem(mc: MemConfig): MemBlackBox = {new rfsp(mc)}    \n",
    "    def sfdpMem(mc: MemConfig): MemBlackBox = {new rfsp(mc)}\n",
    "}\n",
    "\n",
    "object BigFish extends Vendor{\n",
    "    override def genMemWrapper(mc: MemConfig): MemBlackBox = {new rfsp(mc)}\n",
    "}\n",
    "\n",
    "object SPRD extends Vendor{\n",
    "    override def genMemWrapper(mc: MemConfig): MemBlackBox = {new rfsp(mc)}\n",
    "}\n",
    "\n",
    "object ZTE extends Vendor{\n",
    "    override def genMemWrapper(mc: MemConfig): MemBlackBox = {new rfsp(mc)}    \n",
    "    override def genMemWrapper(mc: MemConfig): MemBlackBox = {new rfsp(mc)}\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "case class MemConfig(dw: Int,\n",
    "                     depth: Int,\n",
    "                     maskBitWidth: Int = 0,\n",
    "                     withScan: Boolean = false,\n",
    "                     withBist: Boolean = false,\n",
    "                     withRepaire: Boolean = false){\n",
    "  def bistaw: Int = 14\n",
    "  def aw: Int = log2Up(depth)\n",
    "  def maskName: String = maskBitWidth match {\n",
    "    case 16 => \"wordmask\"\n",
    "    case 8  => \"bytemask\"\n",
    "    case 1  => \"bitmask\"\n",
    "    case 0  => \"nomask\"\n",
    "    case _  => SpinalError(\"Undefiend BWE type\")\n",
    "  }\n",
    "  def bweWidth = if(maskBitWidth == 0) 0 else math.ceil(dw.toDouble/maskBitWidth).toInt\n",
    "  def nonbwe: Boolean = (maskBitWidth == 0)\n",
    "  def needBWE: Boolean = !nonbwe\n",
    "  def genBWE(): Bits = in Bits(bweWidth bits)\n",
    "}\n",
    "\n",
    "class spRAM(mc: MemConfig, memName: String = \"\") extends Component with MemWrap{\n",
    "  val io = new Bundle{\n",
    "    val cs, wr = in Bool()\n",
    "    val bwe    = mc.genBWE()\n",
    "    val addr   = in UInt(mc.aw bits)\n",
    "    val wdata  = in Bits(mc.dw bits)\n",
    "    val rdata  = out Bits(mc.dw bits)\n",
    "  }\n",
    "  // Map the clk\n",
    "  // mapCurrentClockDomain(io.clk)\n",
    "  // Remove io_ prefix\n",
    "   noIoPrefix()\n",
    "//  val ram = new ram_1rw(mc, memName)\n",
    "//  val ram = new vendor.tsmc.mem_1rw(mc, memName)\n",
    "  val ram = new bf_rfsp(mc, memName)\n",
    "  ram.Build(this)\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "class bf_rfsp(mc: MemConfig, memName: String = \"\") extends MemBlackBox{\n",
    "  /*Dirty Temporary solution for deadline, TODO*/\n",
    " \n",
    "  this.setDefinitionName(\"Mwrapper_srsp${mc.depth}x${mc.dw}m16b4w1r\")\n",
    "\n",
    "  val io = new Bundle { iobd =>\n",
    "    val CLK    = in Bool\n",
    "    val A      = in UInt(mc.aw bits)\n",
    "    val D      = in Bits(mc.dw bits)\n",
    "    val CEN    = in Bool()\n",
    "    val WEN    = in Bool()\n",
    "    val Q      = out Bits(mc.dw bits)\n",
    "\n",
    "  val cd  = ClockDomain(io.CLK)\n",
    "\n",
    "  def Build(wrap: spRAM) = {\n",
    "    wrap.clockDomain.setSyncWith(cd)\n",
    "    this.io.CLK  := wrap.clockDomain.readClockWire\n",
    "    this.io.A    := wrap.io.addr\n",
    "    this.io.CEN  := ~wrap.io.cs\n",
    "    this.io.WEN  := ~wrap.io.wr\n",
    "    this.io.D  := wrap.io.wdata\n",
    "    wrap.io.rdata  := this.io.Q\n",
    "  }\n",
    "  noIoPrefix()\n",
    "//  mapClockDomain(clock = io.CLK)\n",
    "\n",
    "  val mem = new Mem(Bits(mc.dw bits), mc.depth)\n",
    " \n",
    "  val ca  = new ClockingArea(cd) {\n",
    "    mem.write(\n",
    "      address = io.A,\n",
    "      data = io.D,\n",
    "      enable = ~io.WEN\n",
    "    )\n",
    "\n",
    "    io.Q := mem.readSync(\n",
    "      address = io.A,\n",
    "      enable = (!io.CEN && io.WEN)\n",
    "    )\n",
    "  }\n",
    "}\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Scala",
   "language": "scala",
   "name": "scala"
  },
  "language_info": {
   "codemirror_mode": "text/x-scala",
   "file_extension": ".scala",
   "mimetype": "text/x-scala",
   "name": "scala",
   "nbconvert_exporter": "script",
   "version": "2.12.8"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
